﻿namespace TwlAction
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// 行为管理器
    /// 思维导图 https://www.processon.com/mindmap/5cee0672e4b0bc8329dee525
    /// 例1 A攻击行为:描述：角色1帧开枪动画+1帧开枪音效+1帧开枪特效+3帧创建子弹(配置Action100001)
    /// 例2 A受伤行为:描述：玩家受伤动画+受伤特效+受伤音效+受伤位移(配置Action500001)
    /// 每执行一个行为 添加到实体身上(实体是否可以同时执行多个行为?)
    /// 例3 A攻击B,A做了100001行为中的伤害行为击中B，B在100002行为中
    /// A的伤害行为有打断效果{
    ///    1.B=>有免疫打断效果(霸体或者无敌), 无法打断其任何行为
    ///    2.B=>没有免疫打断效果(霸体或者无敌),打断行为(有些行为应该在任何情况都无法打断)
    /// }
    /// 
    /// </summary>
    public class ActionMgr : Singleton<ActionMgr>
    {
        private Dictionary<int, BaseAction> actionPool = null;
        private List<int> removeLst = null;
        private List<BaseAction> addLst = null;
        private Dictionary<int, BaseActionPlayer> actionPlayer;

        /// <summary>
        /// 初始化
        /// </summary>
        protected override void initialize()
        {
            actionPool = new Dictionary<int, BaseAction>();
            removeLst = new List<int>();
            addLst = new List<BaseAction>();

            actionPlayer = new Dictionary<int, BaseActionPlayer>();
            actionPlayer.Add(1, new DamageActionPlayer());
            actionPlayer.Add(2, new MoveActionPlayer());
            actionPlayer.Add(3, new AnimActionPlayer());
            actionPlayer.Add(4, new EffectActionPlayer());
            actionPlayer.Add(5, new AudioActionPlayer());
        }

        /// <summary>
        /// 创建一个行为
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public void create<T>(ActionData data) where T : BaseAction, new()
        {
            if (data == null) return;
            if (!actionPool.ContainsKey(data.actionGuid))
            {
                T action = new T();
                action.actionData = data;
                //actionPool.Add(data.actionGuid, action);
                //action.onCreate();
                BaseEntity role = EntityMgr.getRole<BaseEntity>(data.ownerId);
                if (role != null)
                {
                    role.addAction(action);
                    addLst.Add(action);
                }
            }
        }

        //移除技能
        public void remove(ActionData data)
        {
            remove(data.actionGuid);
        }
        //移除技能
        public void remove(int actionGuid)
        {
            removeLst.Add(actionGuid);
        }
        //逻辑帧tick
        public void tick()
        {
            //首先移除行为
            if (removeLst.Count > 0)
            {
                for (int i = 0; i < removeLst.Count; i++)
                {
                    removeAction(removeLst[i]);
                }
                removeLst.Clear();
            }
            //其次添加行为
            if (addLst.Count > 0)
            {
                for (int i = 0; i < addLst.Count; i++)
                {
                    BaseAction action = addLst[i];
                    actionPool.Add(action.actionData.actionGuid, action);
                    action.onCreate();
                }
                addLst.Clear();
            }
            //最后tick行为
            if (actionPool.Count > 0)
            {
                var ier = actionPool.GetEnumerator();
                while (ier.MoveNext())
                {
                    ier.Current.Value.Tick();
                }
                ier.Dispose();
            }
        }
        //移除技能
        private void removeAction(int skillGuid)
        {
            BaseAction action;
            if (actionPool.TryGetValue(skillGuid, out action))
            {
                BaseEntity role = EntityMgr.getRole<BaseEntity>(action.actionData.ownerId);
                if (role != null)
                {
                    role.removeAction(action);
                }
                actionPool.Remove(skillGuid);
                action.onDispose();
            }
        }

        /// <summary>
        /// 技能播放器
        /// </summary>
        /// <param name="actionType"></param> 用枚举有GC
        /// <param name="keyFrame"></param>
        public void playAction(int actionType, ActionData skillData, int cfgId)
        {
            actionPlayer[actionType].playAction(skillData, cfgId);
        }


    }
}
